package com.itheima.gatewaywemedia.filters;

import com.itheima.common.constants.SystemConstants;
import com.itheima.common.util.AppJwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @version 1.0
 * @description 统一网关鉴权，判断用户是否需要登录、登录超时
 * @package com.itheima.gatewaywemedia.filter
 */
@Component
@Slf4j
public class AuthorizeFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // ServerHttpRequest 属于spring的封装
        // HttpServletRequest servlet javaEE的封装 getRequestHeader
        ServerHttpRequest req = exchange.getRequest();
        ServerHttpResponse res = exchange.getResponse();
        //1. 获取请求路径
        String path = req.getURI().getPath();
        log.info("请求了路径: {}", path);
        //2. 判断是否是白名单（登录请求,获取验证码请求）
        // LoginController, 退出、、、 是不需要登录都可以完成
        if(path.startsWith("/wemedia/login")){
            // 放行
            return chain.filter(exchange);
        }
        //3. 非名单：获取请求头信息token信息
        String token = req.getHeaders().getFirst("token");
        //4. 如果没有token值，则返回401，让前端去登录
        //5. 有值，
        if(!StringUtils.isEmpty(token)){
            //校验token有效性
            /*if(SystemConstants.JWT_OK == AppJwtUtil.verifyToken(token)){
                //6. 通过则放行
                return chain.filter(exchange);
            }*/

            // 修改为 解析token来获取载荷
            try {
                // 载荷
                Claims claims = AppJwtUtil.getClaimsBody(token);
                if(null != claims) {
                    // 从载荷中获取登录用户id, 登录成功时，创建token时传了登录用户id给载荷
                    Long wmUserId = claims.get("id", Long.class);
                    // 把登录用户id存入请求头, 随着网关的转发，目标微服就可以从请求头来获取登录用户id
                    // mutate=>转换、转变
                    // 拿请求头来处理一下，//p1:key p2:value
                    // 给请求头添加参数(key=value)
                    req.mutate().header(SystemConstants.USER_HEADER_NAME, wmUserId.toString());
                    return chain.filter(exchange);
                }
            } catch (ExpiredJwtException ex) {
                log.error("token已过期");
            } catch (Exception e) {
                log.error("token无效");
            }
        }
        //7. 返回401，去登录
        res.setStatusCode(HttpStatus.UNAUTHORIZED); //401代表未登录
        return res.setComplete();
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
